﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using GDM.Hogar.Aplicacion.Properties;
using GDM.Hogar.Entidades;
using GDM.Hogar.Entidades.Enums;
using GDM.Hogar.Managers.Contratos;
using GDM.Hogar.Soporte.Helpers;

namespace GDM.Hogar.Aplicacion.Formularios.ParteQuincenalPersonal
{
    public partial class FrmParteQuincenalPersonal
#if DEBUG
 : AdaptadorFrm
#else
     : FrmBase
#endif
    {
        private readonly IParteQuincenalPersonalManager _parteQuincenalPersonalManager;
        private readonly ICodigoAusentismoManager _codigoAusentismoManager;
        private readonly IAgenteManager _agenteManager;
        private BindingSource _bsParteQuincenalPersonal;
        private BindingSource _bsCodigosAusentismo;
        private BindingSource _bsDescripciones;

        protected override string Titulo
        {
            get { return "Parte Quincenal del Personal"; }
        }

        public Action OnParteQuincenalCreado { get; set; }
        public Action OnParteQuincenalActualizado { get; set; }

        private bool EsAdministrativo
        {
            get { return ContextoUsuario.RolId == (int)Rol.Administrativo; }
        }

        public IEnumerable<ConsultaParteQuincenalPersonal> PartesDiarioPersonal { get; set; }

        public FrmParteQuincenalPersonal(IParteQuincenalPersonalManager parteQuincenalPersonalManager, IAgenteManager agenteManager,
                                         ICodigoAusentismoManager codigoAusentismoManager)
        {
            if (parteQuincenalPersonalManager == null)
                throw new ArgumentNullException("parteQuincenalPersonalManager");
            if (agenteManager == null)
                throw new ArgumentNullException("agenteManager");
            if (codigoAusentismoManager == null)
                throw new ArgumentNullException("codigoAusentismoManager");

            _parteQuincenalPersonalManager = parteQuincenalPersonalManager;
            _agenteManager = agenteManager;
            _codigoAusentismoManager = codigoAusentismoManager;
            InitializeComponent();
        }

        private void CargarDatosEncabezado()
        {
            CargarAñosCalendario();
            if (PartesDiarioPersonal != null)
            {
                //-Modo Edicion
                var parteDiario = PartesDiarioPersonal.FirstOrDefault();
                var agentes = new List<ConsultaAgente>
                {
                    new ConsultaAgente
                    {
                        AgenteId = parteDiario.AgenteId,
                        Apellido = parteDiario.Apellido,
                        Nombre = parteDiario.Nombre
                    }
                };
                cmbMes.SelectedIndex = parteDiario.Mes - 1;
                cmbAño.SelectedIndex = cmbAño.FindStringExact(parteDiario.Año.ToString(), 0);
                if (parteDiario.Quincena == 1)
                {
                    rb1rQuincena.Checked = true;
                }
                else
                {
                    rb2daQuincena.Checked = true;
                }
                cmbAgente.CargarItems(agentes, "NombreCompleto", "AgenteId");
                cmbMes.Enabled = false;
                cmbAño.Enabled = false;
                pnlQuincena.Enabled = false;
                cmbAgente.Enabled = false;
                cmbAgente.SelectedIndex = 0;
                txtCarCar.Text = parteDiario.CatCar;
            }
            else
            {
                //-Modo Creacion
                var fechaActual = DateTime.Now;
                cmbMes.SelectedIndex = fechaActual.Month - 1;
                cmbAño.SelectedIndex = cmbAño.FindStringExact(fechaActual.Year.ToString(), 0);
                var agentes = _agenteManager.ObtenerAgentes().Where(x => x.Activo);
                cmbAgente.CargarItems(agentes, "NombreCompleto", "AgenteId", true);
            }
        }

        private void FmrParteQuincenalPersonal_Load(object sender, EventArgs e)
        {
            CargarDatosEncabezado();
            var codigosAusentismo = _codigoAusentismoManager.ObtenerCodigosAusentismo();
            var descripciones = codigosAusentismo.Select(x => new DescripcionCodigo
                {
                    Codigo = x.CodigoAusentismoId, Descripcion = x.Descripcion
                }).ToList();
            _bsCodigosAusentismo = new BindingSource { DataSource = codigosAusentismo };
            _bsDescripciones = new BindingSource{DataSource = descripciones};
            InicializarGrillaParteQuincenalPersonal();
            btnGuardarParteDiario.Visible = EsAdministrativo;
        }

        private void cmbAgente_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbAgente.SelectedIndex > 0)
            {
                var agenteSeleccionado = (ConsultaAgente) cmbAgente.SelectedItem;
                txtCarCar.Text = agenteSeleccionado.Cargo;
            }
            else
            {
                txtCarCar.Clear();
            }
        }

        private void parteDiarioPersonalValidador_CustomValidation(object sender, Controles.Validador.Componentes.ValidationEventArgs e)
        {
            if (e.Control == cmbMes)
            {
                e.Valid = cmbMes.SelectedIndex >= 0;
            }
            if (e.Control == cmbAgente)
            {
                e.Valid = cmbAgente.SelectedIndex > 0;
                if (!e.Valid) txtCarCar.Clear();
            }
            if (e.Control == cmbAño)
            {
                e.Valid = cmbAño.SelectedIndex >= 0;
            }
        }

        private bool ValidarGrilla()
        {
            foreach (DataGridViewRow row in dgvParteQuincenalAgente.Rows)
            {
                foreach (DataGridViewCell cell in row.Cells)
                {
                    ValidarCeldaEnGrilla(cell.RowIndex, cell.ColumnIndex, (string)cell.FormattedValue);
                }
                ValidarFilaEnGrilla(row.Index);

                if (!string.IsNullOrEmpty(row.ErrorText)) continue;

                var error = string.Empty;
                var año = (int)cmbAño.SelectedItem;
                var mes = cmbMes.SelectedIndex + 1;
                var quincena = 1;
                var fecha1 = FechaHelper.InicioPrimerQuincena(mes, año);
                var fecha2 = FechaHelper.FinPrimerQuincena(mes, año);
                //- Validar dia a justificar o periodo fechas
                var diaJustificar = (string) row.Cells[0].FormattedValue;
                var periodoDesde = (string) row.Cells[1].FormattedValue;
                var periodoHasta = (string) row.Cells[2].FormattedValue;
                if (rb2daQuincena.Checked)
                {
                    quincena = 2;
                    fecha1 = FechaHelper.InicioSegundaQuincena(mes, año);
                    fecha2 = FechaHelper.FinSegundaQuincena(mes, año);
                }
                bool filaInvalida;
                if (!string.IsNullOrEmpty(diaJustificar))
                {
                    filaInvalida = !DateTime.Parse(diaJustificar).IsBetween(fecha1, fecha2);
                    if (filaInvalida)
                    {
                        error = string.Format("El dia a justificar no corresponde a la {0} quincena del mes/año",
                                              quincena == 1 ? "primer" : "segunda");
                    }
                }
                else
                {
                    filaInvalida = !DateTime.Parse(periodoDesde).IsBetween(fecha1, fecha2) ||
                                   !DateTime.Parse(periodoHasta).IsBetween(fecha1, fecha2);
                    if (filaInvalida)
                    {
                        error = string.Format("El periodo Desde/Hasta no corresponde a la {0} quincena del mes/año",
                                              quincena == 1 ? "primer" : "segunda");
                    }
                    else
                    {
                        //-valido que el periodo Desde sea menor que el periodo hasta
                        filaInvalida = DateTime.Parse(periodoDesde) >= DateTime.Parse(periodoHasta);
                        if (filaInvalida)
                        {
                            error = "El periodo Desde debe ser menor que el periodo Hasta";
                        }
                    }
                }
                row.ErrorText = error;
            }
            return GrillaValida(dgvParteQuincenalAgente);
        }

        private bool FormularioValido()
        {
            var quincenaSeleccionada = RbSeleccionado(pnlQuincena, pnlQuincena, epQuincena, "Seleccione una Quincena");
            return parteDiarioPersonalValidador.Validate() && quincenaSeleccionada && ValidarGrilla();
        }

        private DatosParteQuincenalPersonal InstanciarParteQuincenalPersonal()
        {
            var parteQuincenalPersonal = new Entidades.ParteQuincenalPersonal
            {
                Mes = cmbMes.SelectedIndex + 1,
                Año = (int)cmbAño.SelectedItem,
                Quincena = rb1rQuincena.Checked ? 1 : 2
            };
            var datosParteQuincenalPersonal = new DatosParteQuincenalPersonal
            {
                ParteQuincenalPersonal = parteQuincenalPersonal,
                DatosParteDiarioPersonal = new List<ParteDiarioPersonal>()
            };
            foreach (DataGridViewRow row in dgvParteQuincenalAgente.Rows)
            {
                var parteDiarioPersonal = (ParteDiarioPersonal)row.DataBoundItem;
                var agenteSeleccionado = (ConsultaAgente) cmbAgente.SelectedItem;
                parteDiarioPersonal.AgenteId = agenteSeleccionado.AgenteId;
                datosParteQuincenalPersonal.DatosParteDiarioPersonal.Add(parteDiarioPersonal);
            }
            return datosParteQuincenalPersonal;
        }

        private void LimpiarFormulario()
        {
            cmbAgente.SelectedIndex = 0;
            _bsParteQuincenalPersonal = new BindingSource();
            dgvParteQuincenalAgente.DataSource = _bsParteQuincenalPersonal;
        }

        private void CrearParteQuincenalPersonal()
        {
            var datosParteQuincenal = InstanciarParteQuincenalPersonal();
            try
            {
                var parteQuincenalPersonalAsXml = XmlHelper.GetXml(datosParteQuincenal);
                parteQuincenalPersonalAsXml = XmlHelper.RemoveAllNamespaces(parteQuincenalPersonalAsXml);
                _parteQuincenalPersonalManager.GuardarParteQuincenalPersonal(parteQuincenalPersonalAsXml);
                MostrarMensajeExito(Resources.ParteDiario_GuardoConExito);
                LimpiarFormulario();
                if (OnParteQuincenalCreado != null)
                {
                    OnParteQuincenalCreado();
                }
            }
            catch (Exception ex)
            {
                MostrarMensajeError(Resources.GuardarParteQuincenal_Error);
            }
        }

        private void ActualizarParteQuincenalPersonal()
        {
            var datosParteQuincenalPersonal = InstanciarParteQuincenalPersonal();
            try
            {
                var parteQuincenalPersonalAsXml = XmlHelper.GetXml(datosParteQuincenalPersonal);
                parteQuincenalPersonalAsXml = XmlHelper.RemoveAllNamespaces(parteQuincenalPersonalAsXml);
                _parteQuincenalPersonalManager.ActualizarParteQuincenalPersonal(parteQuincenalPersonalAsXml);
                MostrarMensajeExito(Resources.ParteDiario_GuardoConExito);
                if (OnParteQuincenalActualizado != null)
                {
                    OnParteQuincenalActualizado();
                }
            }
            catch (Exception ex)
            {
                MostrarMensajeError(Resources.GuardarParteQuincenal_Error);
            }
        }

        private void GuardarRegistro()
        {
            if (!FormularioValido())
            {
                MostrarMensajeError(Resources.ParteQuincenalPersonal_CompleteDatosRequeridos);
                return;
            }
            if (dgvParteQuincenalAgente.Rows.Count == 0)
            {
                MostrarMensajeError(Resources.ParteQuincenalPersonal_CompleteGrilla);
                return;
            }
            else
            {
                if (PartesDiarioPersonal != null)
                {
                    //- Modo Edicion
                    ActualizarParteQuincenalPersonal();
                }
                else
                {
                    //- Modo Creacion
                    var quincena = rb1rQuincena.Checked ? 1 : 2;
                    var agenteSeleccionado = (ConsultaAgente)cmbAgente.SelectedItem;
                    if (_parteQuincenalPersonalManager.ExisteParteQuincenalPersonal((int)cmbAño.SelectedItem, cmbMes.SelectedIndex + 1, quincena, agenteSeleccionado.AgenteId))
                    {
                        MostrarMensajeError(string.Format(Resources.ParteQuincenalPersonal_Existe, quincena == 1 ? "primer" : "segunda", cmbMes.SelectedItem, (int)cmbAño.SelectedItem));
                        return;
                    }
                    CrearParteQuincenalPersonal();
                }
            }
        }

        private void btnGuardarParteDiario_Click(object sender, EventArgs e)
        {
            GuardarRegistro();
        }

        private void btnAgregarPQ_Click(object sender, EventArgs e)
        {
            _bsParteQuincenalPersonal.Add(new ParteDiarioPersonal { DiaJustificar = null, PeriodoDesde = null, PeriodoHasta = null, CodigoAusentismoId = 1});
            dgvParteQuincenalAgente.Rows[dgvParteQuincenalAgente.Rows.Count - 1].ErrorText = Resources.Grilla_Completar_CamposRequeridos;
            dgvParteQuincenalAgente.Rows[dgvParteQuincenalAgente.Rows.Count - 1].Cells[3].ErrorText = Resources.Grilla_Completar_Nombre;
        }

        private void InicializarGrillaParteQuincenalPersonal()
        {
            dgvParteQuincenalAgente.AutoGenerateColumns = false;
            var dgvColumn = (DataGridViewComboBoxColumn)dgvParteQuincenalAgente.Columns["Codigo"];
            if (dgvColumn != null)
            {
                dgvColumn.DisplayMember = "CodigoAusentismoId";
                dgvColumn.ValueMember = "Descripcion";
                dgvColumn.DataSource = _bsCodigosAusentismo;
            }
            var dgvColumn1 = (DataGridViewComboBoxColumn)dgvParteQuincenalAgente.Columns["Descripción"];
            if (dgvColumn1 != null)
            {
                dgvColumn1.DisplayMember = "Descripcion";
                dgvColumn1.ValueMember = "Codigo";
                dgvColumn1.DataSource = _bsDescripciones;
            }
            _bsParteQuincenalPersonal = new BindingSource();
            if (PartesDiarioPersonal != null)
            {
                var partesDiario = PartesDiarioPersonal.Select(x => x.ForceType<ParteDiarioPersonal>());
                _bsParteQuincenalPersonal.DataSource = partesDiario;
            }
            dgvParteQuincenalAgente.DataSource = _bsParteQuincenalPersonal;
            dgvParteQuincenalAgente.ReadOnly = !EsAdministrativo;
            btnAgregarPQ.Visible = EsAdministrativo;
            btnBorrarPQ.Visible = EsAdministrativo;
        }

        private void dgvParteQuincenalAgente_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            var columnIndex = dgvParteQuincenalAgente.CurrentCell.ColumnIndex;
            switch (columnIndex)
            {
                case 0:
                case 1:
                case 2:
                    var fechaActual = DateTime.Now.Date;
                    var dtpFecha = (DateTimePicker) e.Control;
                    dtpFecha.MaxDate = FechaHelper.FinSegundaQuincena(fechaActual.Month, fechaActual.Year);
                    dtpFecha.MinDate = FechaHelper.InicioSegundaQuincena(12, fechaActual.Year - 1);
                    break;
                case 3:
                    var dgvCombo = e.Control as DataGridViewComboBoxEditingControl;
                    dgvCombo.SelectedIndexChanged -= dvgCombo_SelectedIndexChanged;
                    dgvCombo.SelectedIndexChanged += dvgCombo_SelectedIndexChanged;
                    break;
                case 4:
                    var dgvCombo1 = e.Control as DataGridViewComboBoxEditingControl;
                    dgvCombo1.SelectedIndexChanged -= dvgCombo1_SelectedIndexChanged;
                    dgvCombo1.SelectedIndexChanged += dvgCombo1_SelectedIndexChanged;
                    break;
            }
        }

        private void dvgCombo1_SelectedIndexChanged(object sender, EventArgs e)
        {
            var combo = sender as ComboBox;
            var row = dgvParteQuincenalAgente.CurrentRow;
            if (row != null)
            {
                var cell = row.Cells[3] as DataGridViewComboBoxCell;
                if (combo != null)
                {
                    try
                    {
                        var codigoAusentismo = (DescripcionCodigo)combo.SelectedItem;
                        if (codigoAusentismo != null)
                        {
                            cell.Value = combo.SelectedIndex >= 0 ? codigoAusentismo.Codigo : 1;
                            ((ParteDiarioPersonal)row.DataBoundItem).CodigoAusentismoId =
                                codigoAusentismo.Codigo;
                            cell.ErrorText = "";
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                }
            }
        }

        private void dvgCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            var combo = sender as ComboBox;
            var row = dgvParteQuincenalAgente.CurrentRow;
            if (row != null)
            {
                var cell = row.Cells[4] as DataGridViewComboBoxCell;
                if (combo != null)
                {
                    try
                    {
                        var codigoAusentismo = (CodigoAusentismo) combo.SelectedItem;
                        if (codigoAusentismo != null)
                        {
                            cell.Value = combo.SelectedIndex >= 0 ? codigoAusentismo.Descripcion : "";
                            ((ParteDiarioPersonal) row.DataBoundItem).CodigoAusentismoId =
                                codigoAusentismo.CodigoAusentismoId;
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                }
            }
        }

        private void btnBorrarPQ_Click(object sender, EventArgs e)
        {
            if (dgvParteQuincenalAgente.CurrentRow == null) return;

            dgvParteQuincenalAgente.Rows.RemoveAt(dgvParteQuincenalAgente.CurrentRow.Index);
        }

        private void dgvParteQuincenalAgente_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            var dgv = (DataGridView)sender;
            dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "";
        }

        private void ValidarCeldaEnGrilla(int fila, int columna, string valor)
        {
            dgvParteQuincenalAgente.Rows[fila].Cells[columna].ErrorText = string.Empty;
            switch (columna)
            {
                case 0:
                case 1:
                case 2:
                    if (!string.IsNullOrEmpty(valor))
                    {
                        if (DateTime.Parse(valor).IsWeekend())
                        {
                            dgvParteQuincenalAgente.Rows[fila].Cells[columna].ErrorText = "No es una dia laborable";
                            dgvParteQuincenalAgente.Rows[fila].ErrorText = Resources.Grilla_Completar_CamposRequeridos;
                        }
                    }
                    break;
                //-Codigo
                case 3:
                    if (string.IsNullOrEmpty(valor.Trim()))
                    {
                        dgvParteQuincenalAgente.Rows[fila].Cells[columna].ErrorText =
                            Resources.Grilla_Seleccionar_Codigo;
                        dgvParteQuincenalAgente.Rows[fila].ErrorText = Resources.Grilla_Completar_CamposRequeridos;
                    }
                    break;
            }
        }

        private void ValidarFilaEnGrilla(int fila)
        {
            var error = string.Empty;
            var filaInvalida = dgvParteQuincenalAgente.Rows[fila].Cells.Cast<DataGridViewCell>().Any(c => !string.IsNullOrEmpty(c.ErrorText));
            if (!filaInvalida)
            {
                //- Validar dia a justificar o periodo fechas
                var diaJustificar = (string)dgvParteQuincenalAgente.Rows[fila].Cells[0].FormattedValue;
                var periodoDesde = (string)dgvParteQuincenalAgente.Rows[fila].Cells[1].FormattedValue;
                var periodoHasta = (string)dgvParteQuincenalAgente.Rows[fila].Cells[2].FormattedValue;
                if (!string.IsNullOrEmpty(diaJustificar))
                {
                    filaInvalida = !string.IsNullOrEmpty(periodoDesde) || !string.IsNullOrEmpty(periodoHasta);
                }
                else
                {
                    filaInvalida = string.IsNullOrEmpty(periodoDesde) || string.IsNullOrEmpty(periodoHasta);
                }
                if (filaInvalida)
                {
                    error = "Especifique un dia a justificar o un periodo de fechas";
                }
                else
                {
                    //-Valido el dia a justificar con los demas registros del parte quincenal
                    if (!string.IsNullOrEmpty(diaJustificar))
                    {
                        //-validar que no sea parte de un periodo existente o no sea un dia ya repetido
                        foreach (DataGridViewRow row in dgvParteQuincenalAgente.Rows)
                        {
                            if (row.Index == fila) continue;
                            var pd = (string)row.Cells[1].FormattedValue;
                            var ph = (string)row.Cells[2].FormattedValue;
                            var dj = (string)row.Cells[0].FormattedValue;
                            if (!string.IsNullOrEmpty(pd) && !string.IsNullOrEmpty(ph))
                            {
                                //-validar periodo existente
                                var fd = DateTime.Parse(pd);
                                var fh = DateTime.Parse(ph);
                                var djActual = DateTime.Parse(diaJustificar);
                                if (djActual.IsBetween(fd, fh))
                                {
                                    error = "El dia a justificar ya forma parte de un periodo existente";
                                }
                            }
                            else if (!string.IsNullOrEmpty(dj))
                            {
                                //-validar que no sea un dia existente
                                var fj = DateTime.Parse(dj);
                                var fjactual = DateTime.Parse(diaJustificar);
                                if (fjactual.Date.Equals(fj.Date))
                                {
                                    error = "El dia a justificar ya existe en el parte quincenal";
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                error = Resources.Grilla_Completar_CamposRequeridos;
            }
            dgvParteQuincenalAgente.Rows[fila].ErrorText = error;
        }

        private void dgvParteQuincenalAgente_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            ValidarCeldaEnGrilla(e.RowIndex, e.ColumnIndex, (string)e.FormattedValue);
        }

        private void dgvParteQuincenalAgente_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
        {
            ValidarFilaEnGrilla(e.RowIndex);
        }

        private void dgvParteQuincenalAgente_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            e.Cancel = true;
            e.ThrowException = false;
        }

        private void CargarAñosCalendario()
        {
            for (var i = DateTime.Now.Year - 1; i <= DateTime.Now.Year; i++)
            {
                cmbAño.Items.Add(i);
            }
        }

        private void dgvParteQuincenalAgente_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            if (PartesDiarioPersonal == null) return;

            foreach (DataGridViewRow row in dgvParteQuincenalAgente.Rows)
            {
                var cellDescripcion = row.Cells[4] as DataGridViewComboBoxCell;
                var cellCodigo = row.Cells[3] as DataGridViewComboBoxCell;
                var parteDiario = (ParteDiarioPersonal) row.DataBoundItem;
                var parteDiarioBuscado = PartesDiarioPersonal.FirstOrDefault(x => x.ParteDiarioPersonalId == parteDiario.ParteDiarioPersonalId);
                if (parteDiarioBuscado != null)
                {
                    cellDescripcion.Value = parteDiarioBuscado.Codigo;
                    cellCodigo.Value = cellDescripcion.Value;
                }
            }
        }
    }

    internal class DescripcionCodigo
    {
        public int Codigo { get; set; }
        public string Descripcion { get; set; }
    }
}